package com.example.zpositionanimationdemo.chechbox;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.StateElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

import static ohos.agp.components.ComponentState.*;

/**
 * BaseHelper
 *
 * @author ZhongDaFeng
 */
public class RBaseHelper<T extends Component> implements IClip, Component.LayoutRefreshedListener, Component.DrawTask, Component.TouchEventListener {
    /**
     * 自定义背景key
     */
    private static final String background_normal = "background_normal";
    private static final String background_pressed = "background_pressed";
    private static final String background_unable = "background_unable";
    private static final String background_checked = "background_checked";
    private static final String background_selected = "background_selected";

    /**
     * 渐变方向
     */
    private static final String TOP_BOTTOM = "TOP_BOTTOM";
    private static final String TR_BL = "TR_BL";
    private static final String RIGHT_LEFT = "RIGHT_LEFT";
    private static final String BR_TL = "BR_TL";
    private static final String BOTTOM_TOP = "BOTTOM_TOP";
    private static final String BL_TR = "BL_TR";
    private static final String LEFT_RIGHT = "LEFT_RIGHT";
    private static final String TL_BR = "TL_BR";
    private static final String gradient_orientation = "gradient_orientation";
    private static final String corner_radius = "corner_radius";
    private static final String corner_radius_top_left = "corner_radius_top_left";
    private static final String corner_radius_top_right = "corner_radius_top_right";
    private static final String corner_radius_bottom_left = "corner_radius_bottom_left";
    private static final String corner_radius_bottom_right = "corner_radius_bottom_right";

    /**
     * 边框宽度
     */
    private static final String border_width_normal = "border_width_normal";
    private static final String border_width_pressed = "border_width_pressed";
    private static final String border_width_unable = "border_width_unable";
    private static final String border_width_checked = "border_width_checked";
    private static final String border_width_selected = "border_width_selected";

    /**
     * 边框颜色
     */
    private static final String border_color_normal = "border_color_normal";
    private static final String border_color_pressed = "border_color_pressed";
    private static final String border_color_unable = "border_color_unable";
    private static final String border_color_checked = "border_color_checked";
    private static final String border_color_selected = "border_color_selected";
    private static final String gradient_type = "gradient_type";
    private static final String gradient_radius = "gradient_radius";
    private static final String gradient_centerX = "gradient_centerX";
    private static final String gradient_centerY = "gradient_centerY";
    private static final String enabled = "enabled";

    private String strBgType = "";

    /**
     * 背景类型{1:单一颜色值 2:颜色数组 3:图片}
     */
    protected int BG_TYPE_COLOR = 1, BG_TYPE_COLOR_ARRAY = 2, BG_TYPE_IMG = 3;

    //corner
    private float mCornerRadius;

    private float mCornerRadiusTopLeft;
    private float mCornerRadiusTopRight;
    private float mCornerRadiusBottomLeft;
    private float mCornerRadiusBottomRight;

    //BorderWidth
    private float mBorderDashWidth = 0;
    private float mBorderDashGap = 0;
    private int mBorderWidthNormal = 0;
    private int mBorderWidthPressed = 0;
    private int mBorderWidthUnable = 0;
    private int mBorderWidthChecked = 0;
    private int mBorderWidthSelected = 0;

    //BorderColor
    private Color mBorderColorNormal;
    private Color mBorderColorPressed;
    private Color mBorderColorUnable;
    private Color mBorderColorChecked;
    private Color mBorderColorSelected;

    //Background
    private Color mBackgroundColorNormal;
    private Color mBackgroundColorPressed;
    private Color mBackgroundColorUnable;
    private Color mBackgroundColorChecked;
    private Color mBackgroundColorSelected;
    //BackgroundColorArray
    private Color[] mBackgroundColorNormalArray;
    private Color[] mBackgroundColorPressedArray;
    private Color[] mBackgroundColorUnableArray;
    private Color[] mBackgroundColorCheckedArray;
    private Color[] mBackgroundColorSelectedArray;

    private ShapeElement mBackgroundNormal;
    private ShapeElement mBackgroundPressed;
    private ShapeElement mBackgroundUnable;
    private ShapeElement mBackgroundChecked;
    private ShapeElement mBackgroundSelected;
    private Element mBackgroundNormalBmp;
    private Element mBackgroundPressedBmp;
    private Element mBackgroundUnableBmp;
    private Element mBackgroundCheckedBmp;
    private Element mBackgroundSelectedBmp;

    //Gradient
    private int mGradientType = 0;
    private float mGradientRadius;
    private float mGradientCenterX, mGradientCenterY;
    private ShapeElement.Orientation mGradientOrientation = ShapeElement.Orientation.BOTTOM_TO_TOP;
    private int mShadowRadius;

    //View/ViewGroup是否可用
    private boolean mIsEnabled = true;

    //ripple
    private boolean isUseRipple;
    private Color mRippleColor;
    //Ripple波纹限制样式{null, normal=控件矩形, drawable=自定义drawable}

    private Element mViewBackground;//控件默认背景Drawable
    private Element mBackgroundDrawable;

    private int[][] states = new int[6][];
    private StateElement mStateBackground;
    private float[] mBorderRadii = new float[8];

    /**
     * Cache the touch slop from the context that created the view.
     */
    private int mTouchSlop = 0;
    protected Context mContext;

    /**
     * 是否设置对应的属性
     */
    private boolean isHasPressedBgColor = false;
    private boolean isHasPressedBgBmp = false;
    private boolean isHasUnableBgColor = false;
    private boolean isHasUnableBgBmp = false;
    private boolean isHasCheckedBgColor = false;
    private boolean isHasSelectedBgColor = false;
    private boolean isHasCheckedBgBmp = false;
    private boolean isHasSelectedBgBmp = false;
    private boolean isHasPressedBorderColor = false;
    private boolean isHasUnableBorderColor = false;
    private boolean isHasCheckedBorderColor = false;
    private boolean isHasSelectedBorderColor = false;
    private boolean isHasPressedBorderWidth = false;
    private boolean isHasUnableBorderWidth = false;
    private boolean isHasCheckedBorderWidth = false;
    private boolean isHasSelectedBorderWidth = false;

    // view
    protected T mView;

    //EmptyStateListDrawable
    private StateElement emptyStateListDrawable = new StateElement();

    //ClipHelper
    protected ClipHelper mClipHelper = new ClipHelper();
    //clipLayout
    private boolean isClipLayout = false;

    // 水波纹相关属性
    private MmiPoint pointerPosition;
    private int sy;
    private double sx;
    AnimatorValue aValue = new AnimatorValue();
    private double zj;
    private Paint paint;

    /**
     * RBaseHelper
     *
     * @param context 上下文
     * @param view view
     * @param attrs attrs
     */
    public RBaseHelper(Context context, T view, AttrSet attrs) {
        mView = view;
        mContext = context;
        mView.addDrawTask(this);
        mView.setTouchEventListener(this);
        mView.setLayoutRefreshedListener(this);
        initAttributeSet(context, attrs);
        paint = new Paint();
        paint.setColor(mRippleColor);

        paint.setAlpha(0.2f);
        paint.setStyle(Paint.Style.FILL_STYLE);
        aValue.setDuration(1000);
        aValue.setCurveType(Animator.CurveType.LINEAR);
    }

    /**
     * 初始化控件属性
     *
     * @param context 上下文
     * @param attrs attrs
     */
    private void initAttributeSet(Context context, AttrSet attrs) {
        if (context == null || attrs == null) {
            setup();
            return;
        }
        //corner
        mCornerRadius = AttrUtils.getInt(attrs, corner_radius, -1);

        mCornerRadiusTopLeft = AttrUtils.getInt(attrs, corner_radius_top_left, 0);
        mCornerRadiusTopRight = AttrUtils.getInt(attrs, corner_radius_top_right, 0);
        mCornerRadiusBottomLeft = AttrUtils.getInt(attrs, corner_radius_bottom_left, 0);
        mCornerRadiusBottomRight = AttrUtils.getInt(attrs, corner_radius_bottom_right, 0);

        // border
        mBorderWidthNormal = AttrUtils.getInt(attrs, border_width_normal, 0);
        mBorderWidthPressed = AttrUtils.getInt(attrs, border_width_pressed, 0);
        mBorderWidthUnable = AttrUtils.getInt(attrs, border_width_unable, 0);
        mBorderWidthChecked = AttrUtils.getInt(attrs, border_width_checked, 0);
        mBorderWidthSelected = AttrUtils.getInt(attrs, border_width_selected, 0);
        mBorderDashGap = AttrUtils.getFloat(attrs, "border_dash_gap", 0);
        mBorderDashWidth = AttrUtils.getFloat(attrs, "border_dash_width", 0);
        // border 颜色
        mBorderColorNormal = getStringColor(attrs, border_color_normal, null);
        mBorderColorPressed = getStringColor(attrs, border_color_pressed, null);
        mBorderColorUnable = getStringColor(attrs, border_color_unable, null);
        mBorderColorChecked = getStringColor(attrs, border_color_checked, null);
        mBorderColorSelected = getStringColor(attrs, border_color_selected, null);
        strBgType = AttrUtils.getXmlManyValue(attrs, "bgType", "color");

        Object[] bgInfoNormal;

        bgInfoNormal = getBackgroundInfo(attrs, background_normal);

        mBackgroundColorNormal = (Color) bgInfoNormal[1];
        mBackgroundColorNormalArray = (Color[]) bgInfoNormal[2];
        mBackgroundNormalBmp = (Element) bgInfoNormal[3];

        //pressed
        Object[] bgInfoPressed = getBackgroundInfo(attrs, background_pressed);
        mBackgroundColorPressed = (Color) bgInfoPressed[1];
        mBackgroundColorPressedArray = (Color[]) bgInfoPressed[2];
        mBackgroundPressedBmp = (Element) bgInfoPressed[3];
        //unable
        Object[] bgInfoUnable = getBackgroundInfo(attrs, background_unable);
        mBackgroundColorUnable = (Color) bgInfoUnable[1];
        mBackgroundColorUnableArray = (Color[]) bgInfoUnable[2];
        mBackgroundUnableBmp = (Element) bgInfoUnable[3];
        //checked
        Object[] bgInfoChecked = getBackgroundInfo(attrs, background_checked);
        mBackgroundColorChecked = (Color) bgInfoChecked[1];
        mBackgroundColorCheckedArray = (Color[]) bgInfoChecked[2];
        mBackgroundCheckedBmp = (Element) bgInfoChecked[3];
        //selected
        Object[] bgInfoSelected = getBackgroundInfo(attrs, background_selected);
        mBackgroundColorSelected = (Color) bgInfoSelected[1];
        mBackgroundColorSelectedArray = (Color[]) bgInfoSelected[2];
        mBackgroundSelectedBmp = (Element) bgInfoSelected[3];
        //gradient
        mGradientType = AttrUtils.getInt(attrs, gradient_type, 0);
        mGradientOrientation = getGradientOrientation(attrs);

        mGradientRadius = AttrUtils.getFloat(attrs, gradient_radius, -1);
        mGradientCenterX = AttrUtils.getFloat(attrs, gradient_centerX, 0.5f);
        mGradientCenterY = AttrUtils.getFloat(attrs, gradient_centerY, 0.5f);

        //enabled
        mIsEnabled = getBool(attrs, enabled, "true");

        //Ripple
        try {
            isUseRipple = getBool(attrs, "ripple", "false");
            mRippleColor = getStringColor(attrs, "ripple_color", null);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //shadow
        mShadowRadius = AttrUtils.getInt(attrs, "shadow_radius", -1);

        //clip
        isClipLayout = getBool(attrs, "clip_layout", "false");

        isHasPressedBgColor = mBackgroundColorPressed != null || mBackgroundColorPressedArray != null;
        isHasUnableBgColor = mBackgroundColorUnable != null || mBackgroundColorUnableArray != null;
        isHasCheckedBgColor = mBackgroundColorChecked != null || mBackgroundColorCheckedArray != null;
        isHasSelectedBgColor = mBackgroundColorSelected != null || mBackgroundColorSelectedArray != null;
        isHasPressedBgBmp = mBackgroundPressedBmp != null;
        isHasUnableBgBmp = mBackgroundUnableBmp != null;
        isHasCheckedBgBmp = mBackgroundCheckedBmp != null;
        isHasSelectedBgBmp = mBackgroundSelectedBmp != null;

        isHasPressedBorderColor = mBorderColorPressed != null;

        isHasUnableBorderColor = mBorderColorUnable != null;
        isHasCheckedBorderColor = mBorderColorChecked != null;
        isHasSelectedBorderColor = mBorderColorSelected != null;
        isHasPressedBorderWidth = mBorderWidthPressed != 0;
        isHasUnableBorderWidth = mBorderWidthUnable != 0;
        isHasCheckedBorderWidth = mBorderWidthChecked != 0;
        isHasSelectedBorderWidth = mBorderWidthSelected != 0;
        setup();
    }

    private boolean getBool(AttrSet attrs, String aEnabled, String s) {
        String bool = AttrUtils.getString(attrs, aEnabled, s);
        return bool.toLowerCase().equals("true");
    }

    private Color getStringColor(AttrSet attrs, String colorKey, String s) {
        String color = AttrUtils.getString(attrs, colorKey, s);
        if (color == null) {
            return Color.TRANSPARENT;
        }
        return new Color(Color.getIntColor(color));
    }

    /**
     * 设置
     */
    private void setup() {
        /*
         * 如果本身为true，则由自定义属性决定
         * 如果本身为false，则由原生属性决定
         * ViewGroup Always true
         */
        boolean isEnabled = mView.isEnabled();
        if (isEnabled) mView.setEnabled(mIsEnabled);

        mBackgroundNormal = new ShapeElement();
        mBackgroundPressed = new ShapeElement();
        mBackgroundUnable = new ShapeElement();
        mBackgroundChecked = new ShapeElement();
        mBackgroundSelected = new ShapeElement();
        mViewBackground = mView.getBackgroundElement();
        mStateBackground = new StateElement();

        /*
         * 设置背景默认值
         * 备注:当存在 Checked 状态并且没有设置 Pressed 时，Pressed = Checked 更符合常规UI
         */
        if (!isHasPressedBgColor) {
            mBackgroundColorPressed = isHasCheckedBgColor ? mBackgroundColorChecked : mBackgroundColorNormal;
            mBackgroundColorPressedArray = isHasCheckedBgColor ? mBackgroundColorCheckedArray : mBackgroundColorNormalArray;
        }
        if (!isHasPressedBgBmp) {
            mBackgroundPressedBmp = isHasCheckedBgBmp ? mBackgroundCheckedBmp : mBackgroundNormalBmp;
        }
        if (!isHasUnableBgColor) {
            mBackgroundColorUnable = mBackgroundColorNormal;
            mBackgroundColorUnableArray = mBackgroundColorNormalArray;
        }
        if (!isHasUnableBgBmp) {
            mBackgroundUnableBmp = mBackgroundNormalBmp;
        }
        if (!isHasCheckedBgColor) {
            mBackgroundColorChecked = mBackgroundColorNormal;
            mBackgroundColorCheckedArray = mBackgroundColorNormalArray;
        }
        if (!isHasSelectedBgColor) {
            mBackgroundColorSelected = mBackgroundColorNormal;
            mBackgroundColorSelectedArray = mBackgroundColorNormalArray;
        }
        if (!isHasCheckedBgBmp) {
            mBackgroundCheckedBmp = mBackgroundNormalBmp;
        }
        if (!isHasSelectedBgBmp) {
            mBackgroundSelectedBmp = mBackgroundNormalBmp;
        }

        /*
         * 设置背景颜色（包含渐变）
         */
        if (mBackgroundColorNormalArray != null && mBackgroundColorNormalArray.length > 0) {
            mBackgroundNormal = setColors(mBackgroundNormal, ColorArrayToIntArray(mBackgroundColorNormalArray));
        } else {
            if (mBackgroundColorNormal != null) {
                mBackgroundNormal.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorNormal.getValue()));
            }
        }
        if (mBackgroundColorPressedArray != null && mBackgroundColorPressedArray.length > 0) {
            mBackgroundPressed = setColors(mBackgroundPressed, ColorArrayToIntArray(mBackgroundColorPressedArray));
        } else {
            if (mBackgroundColorPressed != null) {
                mBackgroundPressed.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorPressed.getValue()));
            }
        }
        if (mBackgroundColorUnableArray != null && mBackgroundColorUnableArray.length > 0) {
            mBackgroundUnable = setColors(mBackgroundUnable, ColorArrayToIntArray(mBackgroundColorUnableArray));
        } else {
            if (mBackgroundColorUnable != null) {
                mBackgroundUnable.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorUnable.getValue()));
            }
        }
        if (mBackgroundColorCheckedArray != null && mBackgroundColorCheckedArray.length > 0) {
            mBackgroundChecked = setColors(mBackgroundChecked, ColorArrayToIntArray(mBackgroundColorCheckedArray));
        } else {
            if (mBackgroundColorChecked != null) {
                mBackgroundChecked.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorChecked.getValue()));
            }
        }
        if (mBackgroundColorSelectedArray != null && mBackgroundColorSelectedArray.length > 0) {
            mBackgroundSelected = setColors(mBackgroundSelected, ColorArrayToIntArray(mBackgroundColorSelectedArray));
        } else {
            if (mBackgroundColorSelected != null) {
                mBackgroundSelected.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorSelected.getValue()));
            }
        }

        setGradient();

        //unable,focused,pressed,checked,selected,normal
        states[0] = new int[]{COMPONENT_STATE_DISABLED};//unable
        states[1] = new int[]{COMPONENT_STATE_FOCUSED};//focused
        states[2] = new int[]{COMPONENT_STATE_PRESSED};//pressed
        states[3] = new int[]{COMPONENT_STATE_CHECKED};//checked
        states[4] = new int[]{COMPONENT_STATE_SELECTED};//selected
        states[5] = new int[]{COMPONENT_STATE_EMPTY};//normal

        //unable,focused,pressed,checked,normal
        mStateBackground.addState(states[0], mBackgroundUnableBmp == null ? mBackgroundUnable : mBackgroundUnableBmp);
        mStateBackground.addState(states[1], mBackgroundPressedBmp == null ? mBackgroundPressed : mBackgroundPressedBmp);
        mStateBackground.addState(states[2], mBackgroundPressedBmp == null ? mBackgroundPressed : mBackgroundPressedBmp);
        mStateBackground.addState(states[3], mBackgroundCheckedBmp == null ? mBackgroundChecked : mBackgroundCheckedBmp);
        mStateBackground.addState(states[4], mBackgroundSelectedBmp == null ? mBackgroundSelected : mBackgroundSelectedBmp);
        mStateBackground.addState(states[5], mBackgroundNormalBmp == null ? mBackgroundNormal : mBackgroundNormalBmp);

        /*
         * 设置边框默认值
         */
        if (!isHasPressedBorderWidth) {
            mBorderWidthPressed = isHasCheckedBorderWidth ? mBorderWidthChecked : mBorderWidthNormal;
        }
        if (!isHasUnableBorderWidth) {
            mBorderWidthUnable = mBorderWidthNormal;
        }
        if (!isHasCheckedBorderWidth) {
            mBorderWidthChecked = mBorderWidthNormal;
        }
        if (!isHasSelectedBorderWidth) {
            mBorderWidthSelected = mBorderWidthNormal;
        }
        if (!isHasPressedBorderColor) {
            mBorderColorPressed = isHasCheckedBorderColor ? mBorderColorChecked : mBorderColorNormal;
        }
        if (!isHasUnableBorderColor) {
            mBorderColorUnable = mBorderColorNormal;
        }
        if (!isHasCheckedBorderColor) {
            mBorderColorChecked = mBorderColorNormal;
        }
        if (!isHasSelectedBorderColor) {
            mBorderColorSelected = mBorderColorNormal;
        }

        //设置边框
        setBorder();
        //设置圆角
        setRadiusValue();
    }

    private int[] ColorArrayToIntArray(Color[] array) {
        int[] intArray = new int[0];
        if (array != null) {
            intArray = new int[array.length];
            for (int i = 0; i < array.length; i++) {
                intArray[i] = array[i].getValue();
            }
            return intArray;
        } else {
            return intArray;
        }
    }

    /**
     * Gradient
     *
     * @return float
     */
    public float getGradientRadius() {
        return mGradientRadius;
    }

    public float getGradientCenterX() {
        return mGradientCenterX;
    }

    public float getGradientCenterY() {
        return mGradientCenterY;
    }

    public int getGradientType() {
        return mGradientType;
    }

    /**
     * setGradientRadius
     *
     * @param gradientRadius gradientRadius
     * @return RBaseHelper
     */
    public RBaseHelper setGradientRadius(float gradientRadius) {
        this.mGradientRadius = gradientRadius;
        setGradient();
        setBackgroundState();
        return this;
    }

    /**
     * setGradientCenterX
     *
     * @param gradientCenterX gradientCenterX
     * @return RBaseHelper
     */
    public RBaseHelper setGradientCenterX(float gradientCenterX) {
        this.mGradientCenterX = gradientCenterX;
        setGradient();
        setBackgroundState();
        return this;
    }

    /**
     * setGradientCenterY
     *
     * @param gradientCenterY gradientCenterY
     * @return RBaseHelper
     */
    public RBaseHelper setGradientCenterY(float gradientCenterY) {
        this.mGradientCenterY = gradientCenterY;
        setGradient();
        setBackgroundState();
        return this;
    }

    /**
     * 设置渐变样式/类型
     *
     * @param gradientType {LINEAR_GRADIENT=0, RADIAL_GRADIENT=1, SWEEP_GRADIENT=2}
     * @return RBaseHelper
     */
    public RBaseHelper setGradientType(int gradientType) {
        if (gradientType < 0 || gradientType > 2) {
            gradientType = 0;
        }
        this.mGradientType = gradientType;
        setGradient();
        setBackgroundState();
        return this;
    }

    /**
     * setGradientOrientation
     *
     * @param orientation orientation
     * @return RBaseHelper
     */
    public RBaseHelper setGradientOrientation(ShapeElement.Orientation orientation) {
        this.mGradientOrientation = orientation;
        setGradient();
        setBackgroundState();
        return this;
    }

    private void setGradient() {
        mBackgroundNormal.setShaderType(mGradientType);
        mBackgroundNormal.setCornerRadius(mGradientRadius);
        mBackgroundPressed.setShaderType(mGradientType);
        mBackgroundPressed.setCornerRadius(mGradientRadius);
        mBackgroundUnable.setShaderType(mGradientType);
        mBackgroundUnable.setCornerRadius(mGradientRadius);
        mBackgroundChecked.setShaderType(mGradientType);
        mBackgroundChecked.setCornerRadius(mGradientRadius);
        mBackgroundSelected.setShaderType(mGradientType);
        mBackgroundSelected.setCornerRadius(mGradientRadius);
    }

    /**
     * BackgroundColor
     *
     * @param normal normal
     * @param pressed pressed
     * @param unable unable
     * @param checked checked
     * @param selected selected
     * @return RBaseHelper
     */

    public RBaseHelper setStateBackgroundColor(Color normal, Color pressed, Color unable, Color checked, Color selected) {
        mBackgroundColorNormal = normal;
        mBackgroundColorPressed = pressed;
        mBackgroundColorUnable = unable;
        mBackgroundColorChecked = checked;
        mBackgroundColorSelected = selected;
        isHasPressedBgColor = true;
        isHasUnableBgColor = true;
        isHasCheckedBgColor = true;
        isHasSelectedBgColor = true;
        mBackgroundNormal.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorNormal.getValue()));
        mBackgroundPressed.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorPressed.getValue()));
        mBackgroundUnable.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorUnable.getValue()));
        mBackgroundChecked.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorChecked.getValue()));
        mBackgroundSelected.setRgbColor(RgbColor.fromArgbInt(mBackgroundColorSelected.getValue()));
        setBackgroundState();
        return this;
    }

    /**
     * setStateBackgroundColor
     *
     * @param normal normal
     * @param pressed pressed
     * @param unable unable
     * @param checked checked
     * @param selected selected
     * @return RBaseHelper
     */

    public RBaseHelper setStateBackgroundColor(Element normal, Element pressed, Element unable, Element checked, Element selected) {
        mBackgroundNormalBmp = normal;
        mBackgroundPressedBmp = pressed;
        mBackgroundUnableBmp = unable;
        mBackgroundCheckedBmp = checked;
        mBackgroundSelectedBmp = selected;
        isHasPressedBgBmp = true;
        isHasUnableBgBmp = true;
        isHasCheckedBgBmp = true;
        isHasSelectedBgBmp = true;
        refreshStateListDrawable();
        setBackgroundState();
        return this;
    }

    /**
     * 刷新StateListDrawable状态
     * 更新drawable背景时时候刷新
     */
    private void refreshStateListDrawable() {
        mStateBackground = emptyStateListDrawable;
        //unable,focused,pressed,checked,selected,normal
        mStateBackground.addState(states[0], mBackgroundUnableBmp == null ? mBackgroundUnable : mBackgroundUnableBmp);
        mStateBackground.addState(states[1], mBackgroundPressedBmp == null ? mBackgroundPressed : mBackgroundPressedBmp);
        mStateBackground.addState(states[2], mBackgroundPressedBmp == null ? mBackgroundPressed : mBackgroundPressedBmp);
        mStateBackground.addState(states[3], mBackgroundCheckedBmp == null ? mBackgroundChecked : mBackgroundCheckedBmp);
        mStateBackground.addState(states[4], mBackgroundSelectedBmp == null ? mBackgroundSelected : mBackgroundSelectedBmp);
        mStateBackground.addState(states[5], mBackgroundNormalBmp == null ? mBackgroundNormal : mBackgroundNormalBmp);
    }

    private void setBackgroundState() {
        boolean isHasCustom = false;//是否存在自定义
        boolean isHasCusBg, hasCusBorder = false, hasCusCorner = false;//存在自定义相关属性
        boolean isUnHasBgColor = mBackgroundColorNormal == null && mBackgroundColorUnable == null && mBackgroundColorPressed == null && mBackgroundColorChecked == null && mBackgroundColorSelected == null;
        boolean isUnHasBgColorArray = mBackgroundColorNormalArray == null && mBackgroundColorUnableArray == null && mBackgroundColorPressedArray == null && mBackgroundColorCheckedArray == null && mBackgroundColorSelectedArray == null;
        boolean isUnHasBgDrawable = mBackgroundNormalBmp == null && mBackgroundPressedBmp == null && mBackgroundUnableBmp == null && mBackgroundCheckedBmp == null && mBackgroundSelectedBmp == null;

        //是否自定义了背景
        if (isUnHasBgColor && isUnHasBgColorArray && isUnHasBgDrawable) {
            //未设置自定义背景
            isHasCusBg = false;
        } else {
            isHasCusBg = true;
        }

        //是否自定义了边框
        if (mBorderDashWidth != 0 || mBorderDashGap != 0
                || mBorderWidthNormal != 0 || mBorderWidthPressed != 0 || mBorderWidthUnable != 0 || mBorderWidthChecked != 0 || mBorderWidthSelected != 0
                || mBorderColorNormal != Color.TRANSPARENT || mBorderColorPressed != Color.TRANSPARENT || mBorderColorUnable != Color.TRANSPARENT || mBorderColorChecked != Color.TRANSPARENT || mBorderColorSelected != Color.TRANSPARENT) {
            hasCusBorder = true;
        }
        //是否自定义了圆角
        if (mCornerRadius != -1 || mCornerRadiusTopLeft != 0 || mCornerRadiusTopRight != 0 || mCornerRadiusBottomLeft != 0 || mCornerRadiusBottomRight != 0) {
            hasCusCorner = true;
        }

        if (isHasCusBg || hasCusCorner || hasCusBorder) {
            isHasCustom = true;
        }

        /*
         * 未设置自定义属性,获取原生背景并且设置
         */
        if (!isHasCustom && !useRipple()) {
            mBackgroundDrawable = mViewBackground;//使用原生背景
        } else {
            mBackgroundDrawable = getBackgroundDrawable(isHasCustom, mRippleColor);
        }

        /*
         * 存在自定义属性，使用自定义属性设置
         */
        mView.setBackground(mBackgroundDrawable);
    }

    /**
     * 获取 BackgroundDrawable
     *
     * @param isHasCustom 是否存在自定义背景
     * @param rippleColor 水波纹颜色
     * @return Element
     */
    private Element getBackgroundDrawable(boolean isHasCustom, Color rippleColor) {
        if (!isUseRipple()) {
            return mStateBackground;
        } else {
            /*
             * 使用Ripple时兼容Pressed之外的状态
             * 备注:水波纹效果受限于控件
             * 构建一种新的状态，兼容存在 RippleDrawable 和其他状态
             */
            StateElement stateBackground = new StateElement();
            int[][] states = new int[6][];
            //unable,checked,selected,normal
            states[0] = new int[]{COMPONENT_STATE_DISABLED};//unable
            states[1] = new int[]{COMPONENT_STATE_CHECKED};//checked
            states[2] = new int[]{COMPONENT_STATE_SELECTED};//selected
            states[3] = new int[]{COMPONENT_STATE_FOCUSED};//FOUSED
            states[4] = new int[]{COMPONENT_STATE_PRESSED};//PRESS
            states[5] = new int[]{COMPONENT_STATE_EMPTY};//PRESS
            //unable,checked,normal
            stateBackground.addState(states[0], mBackgroundUnable);
            stateBackground.addState(states[1], mBackgroundChecked);
            stateBackground.addState(states[2], mBackgroundSelected);
            stateBackground.addState(states[3], mBackgroundPressed);
            stateBackground.addState(states[4], mBackgroundPressed);

            stateBackground.addState(states[5], mBackgroundNormal);
            return stateBackground;
        }
    }

    /*
     * 获取 RippleDrawable 和 特殊标记
     *
     * @param hasCustom 是否存在自定义背景
     * @param rippleColor 水波纹颜色
     */

    /**
     * Shadow
     *
     * @return boolean
     */
    public boolean useShadow() {
        return mShadowRadius >= 0;
    }

    /**
     * useRipple
     *
     * @return boolean
     */
    public boolean useRipple() {
        return isUseRipple;
    }

    /**
     * setBorderWidthPressed
     *
     * @param width 宽
     * @return RBaseHelper
     */
    public RBaseHelper setBorderWidthPressed(int width) {
        this.mBorderWidthPressed = width;
        this.isHasPressedBorderWidth = true;
        setBorderPressed();
        return this;
    }

    /**
     * setBorderColorPressed
     *
     * @param color 颜色
     * @return RBaseHelper
     */
    public RBaseHelper setBorderColorPressed(Color color) {
        this.mBorderColorPressed = color;
        this.isHasPressedBorderColor = true;
        setBorderPressed();
        return this;
    }

    public Color getBorderColorPressed() {
        return mBorderColorPressed;
    }

    /**
     * setBorderColorChecked
     *
     * @param color 颜色
     * @return RBaseHelper
     */
    public RBaseHelper setBorderColorChecked(Color color) {
        this.mBorderColorChecked = color;
        this.isHasCheckedBorderColor = true;
        if (!isHasPressedBorderColor) mBorderColorPressed = mBorderColorChecked;
        setBorderChecked();
        return this;
    }

    /**
     * setBorderWidthChecked
     *
     * @param width 宽
     * @return RBaseHelper
     */
    public RBaseHelper setBorderWidthChecked(int width) {
        this.mBorderWidthChecked = width;
        this.isHasCheckedBorderWidth = true;
        if (!isHasPressedBorderWidth) mBorderWidthPressed = mBorderWidthChecked;
        setBorderChecked();
        return this;
    }

     private void setBorder() {
        float[] floats = new float[2];
        floats[0] = mBorderDashGap;
        floats[1] = mBorderDashWidth;

        mBackgroundNormal.setStroke(mBorderWidthNormal, RgbColor.fromArgbInt(mBorderColorNormal.getValue()));
        mBackgroundNormal.setDashPathEffectValues(floats, 0);
        mBackgroundPressed.setStroke(mBorderWidthPressed, RgbColor.fromArgbInt(mBorderColorPressed.getValue()));
        mBackgroundPressed.setDashPathEffectValues(floats, 0);
        mBackgroundUnable.setStroke(mBorderWidthUnable, RgbColor.fromArgbInt(mBorderColorUnable.getValue()));
        mBackgroundUnable.setDashPathEffectValues(floats, 0);
        mBackgroundChecked.setStroke(mBorderWidthChecked, RgbColor.fromArgbInt(mBorderColorChecked.getValue()));
        mBackgroundChecked.setDashPathEffectValues(floats, 0);
        mBackgroundSelected.setStroke(mBorderWidthSelected, RgbColor.fromArgbInt(mBorderColorSelected.getValue()));
        mBackgroundSelected.setDashPathEffectValues(floats, 0);

        setBackgroundState();
    }

    private void setBorderNormal() {
        mBackgroundNormal.setStroke(mBorderWidthNormal, RgbColor.fromArgbInt(mBorderColorNormal.getValue()));
        setBackgroundState();
    }

    private void setBorderPressed() {
        mBackgroundPressed.setStroke(mBorderWidthPressed, RgbColor.fromArgbInt(mBorderColorPressed.getValue()));
        setBackgroundState();
    }

    private void setBorderUnable() {
        mBackgroundUnable.setStroke(mBorderWidthUnable, RgbColor.fromArgbInt(mBorderColorUnable.getValue()));
        setBackgroundState();
    }

    private void setBorderChecked() {
        mBackgroundChecked.setStroke(mBorderWidthChecked, RgbColor.fromArgbInt(mBorderColorChecked.getValue()));
        setBackgroundState();
    }

    private void setBorderSelected() {
        mBackgroundSelected.setStroke(mBorderWidthSelected, RgbColor.fromArgbInt(mBorderColorSelected.getValue()));
        setBackgroundState();
    }

    /**
     * 设置圆角UI
     */
    private void setRadiusUI() {
        mBackgroundNormal.setCornerRadiiArray(mBorderRadii);
        mBackgroundPressed.setCornerRadiiArray(mBorderRadii);
        mBackgroundUnable.setCornerRadiiArray(mBorderRadii);
        mBackgroundChecked.setCornerRadiiArray(mBorderRadii);
        mBackgroundSelected.setCornerRadiiArray(mBorderRadii);
        setBackgroundState();
    }

    /**
     * 设置圆角数值
     */
    private void setRadiusValue() {
        if (mCornerRadius >= 0) {
            mBorderRadii[0] = DensityUtils.pxToFp(mContext, mCornerRadius);
            mBorderRadii[1] = DensityUtils.pxToFp(mContext, mCornerRadius);
            mBorderRadii[2] = DensityUtils.pxToFp(mContext, mCornerRadius);
            mBorderRadii[3] = DensityUtils.pxToFp(mContext, mCornerRadius);
            mBorderRadii[4] = DensityUtils.pxToFp(mContext, mCornerRadius);
            mBorderRadii[5] = DensityUtils.pxToFp(mContext, mCornerRadius);
            mBorderRadii[6] = DensityUtils.pxToFp(mContext, mCornerRadius);
            mBorderRadii[7] = DensityUtils.pxToFp(mContext, mCornerRadius);
            setRadiusUI();
            return;
        }

        if (mCornerRadius < 0) {
            mBorderRadii[0] = DensityUtils.pxToFp(mContext, mCornerRadiusTopLeft);
            mBorderRadii[1] = DensityUtils.fpToPx(mContext, mCornerRadiusTopLeft);
            mBorderRadii[2] = DensityUtils.fpToPx(mContext, mCornerRadiusTopRight);
            mBorderRadii[3] = DensityUtils.fpToPx(mContext, mCornerRadiusTopRight);
            mBorderRadii[4] = DensityUtils.fpToPx(mContext, mCornerRadiusBottomRight);
            mBorderRadii[5] = DensityUtils.fpToPx(mContext, mCornerRadiusBottomRight);
            mBorderRadii[6] = DensityUtils.fpToPx(mContext, mCornerRadiusBottomLeft);
            mBorderRadii[7] = DensityUtils.fpToPx(mContext, mCornerRadiusBottomLeft);
            setRadiusUI();
            return;
        }
    }

    /**
     * 设置View大小变化监听,用来更新渐变半径
     */
    private void addOnGlobalLayoutListener() {
    }

    /**
     * 获取背景颜色
     * 备注:
     * 数组[0]:背景类型(1:单一颜色 2:颜色数组 3:图片资源)
     * 数组[1]:单一颜色,可能为0
     * 数组[2]:颜色数组,可能为null
     * 数组[3]:图片资源drawable,可能为null
     * 单个图片背景 或多个颜色背景
     *
     * @param attr AttrSet
     * @param key String
     * @return Object
     */
    private Object[] getBackgroundInfo(AttrSet attr, String key) {
        Color[] colors = null;

        int bgType = BG_TYPE_COLOR;//背景类型
        String[] bgColorArray = null;//多个颜色
        Color bgColor = null; // 单一颜色
        Element bgElement = null;
        if (strBgType.equals("color")) {
            bgType = BG_TYPE_COLOR;
            bgColor = getStringColor(attr, key, "#ffffff");
        } else if (strBgType.equals("colorArray")) {
            String colorList = AttrUtils.getXmlManyValue(attr, key, null);

            if (colorList != null) {
                bgColorArray = colorList.split(",");
                colors = new Color[bgColorArray.length];
                for (int i = 0; i < bgColorArray.length; i++) {
                    colors[i] = new Color(Color.getIntColor(bgColorArray[i]));
                }
                bgType = BG_TYPE_COLOR_ARRAY;
            }
        } else if (strBgType.equals("element")) {
            bgType = BG_TYPE_IMG;
            // 图片背景类型
            bgElement = AttrUtils.getElement(attr, key, null);
        }
        return new Object[]{bgType, bgColor, colors, bgElement};
    }

    /**
     * 获取渐变方向
     *
     * @param attr AttrSet
     * @return ShapeElement
     */
    private ShapeElement.Orientation getGradientOrientation(AttrSet attr) {
        String orientationValue = AttrUtils.getString(attr, gradient_orientation, BL_TR).toUpperCase();
        ShapeElement.Orientation orientation = ShapeElement.Orientation.BOTTOM_LEFT_TO_TOP_RIGHT;
        switch (orientationValue) {
            case TOP_BOTTOM:
                orientation = ShapeElement.Orientation.TOP_TO_BOTTOM;
                break;
            case TR_BL:
                orientation = ShapeElement.Orientation.TOP_RIGHT_TO_BOTTOM_LEFT;
                break;
            case RIGHT_LEFT:
                orientation = ShapeElement.Orientation.RIGHT_TO_LEFT;
                break;
            case BR_TL:
                orientation = ShapeElement.Orientation.BOTTOM_RIGHT_TO_TOP_LEFT;
                break;
            case BOTTOM_TOP:
                orientation = ShapeElement.Orientation.BOTTOM_TO_TOP;
                break;
            case BL_TR:
                orientation = ShapeElement.Orientation.BOTTOM_LEFT_TO_TOP_RIGHT;
                break;
            case LEFT_RIGHT:
                orientation = ShapeElement.Orientation.LEFT_TO_RIGHT;
                break;
            case TL_BR:
                orientation = ShapeElement.Orientation.TOP_LEFT_TO_BOTTOM_RIGHT;
                break;
        }
        return orientation;
    }

    /**
     * 设置GradientDrawable颜色数组,兼容版本
     *
     * @param drawable GradientDrawable
     * @param colors 颜色数组
     * @return ShapeElement
     */
    private ShapeElement setColors(ShapeElement drawable, int[] colors) {
        drawable = new ShapeElement();
        drawable.setOrientation(mGradientOrientation);
        RgbColor[] rgbColors = new RgbColor[colors.length];
        for (int i = 0; i < colors.length; i++) {
            RgbColor color = RgbColor.fromArgbInt(colors[i]);
            rgbColors[i] = color;
        }
        drawable.setRgbColors(rgbColors);
        return drawable;
    }

    /**
     * 是否移出view
     *
     * @param x int
     * @param y int
     * @return boolean
     */
    protected boolean isOutsideView(int x, int y) {
        boolean isFlag = false;
        // Be lenient about moving outside of buttons
        if ((x < 0 - mTouchSlop) || (x >= mView.getWidth() + mTouchSlop) ||
                (y < 0 - mTouchSlop) || (y >= mView.getHeight() + mTouchSlop)) {
            // Outside button
            isFlag = true;
        }
        return isFlag;
    }

    /**
     * 是否使用Ripple
     *
     * @return boolean
     */
    private boolean isUseRipple() {
        return isUseRipple;
    }

    /**
     * 初始化Clip
     */
    private void initClip() {
        //初始化clip
        mClipHelper.initClip(mView, isClipLayout, new ClipPathManager.ClipPathCreator() {
            @Override
            public Path createClipPath(int width, int height) {
                Path path = new Path();
                path.addRoundRect(new RectFloat(0, 0, width, height), mBorderRadii, Path.Direction.COUNTER_CLOCK_WISE);
                return path;
            }
        });
    }

    @Override
    public void dispatchDraw(Canvas canvas) {
        mClipHelper.dispatchDraw(canvas);
    }

    @Override
    public void onLayout(int left, int top, int right, int bottom) {
        mClipHelper.onLayout(left, top, right, bottom);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        if (isUseRipple && mView.isEnabled()) {
            pointerPosition = event.getPointerPosition(0);
            double x = (double) pointerPosition.getX();
            double y = (double) pointerPosition.getY();
            int[] parentLocationOnScreen = mView.getLocationOnScreen();
            int yy = (int) (y - parentLocationOnScreen[1]);
            sx = x - parentLocationOnScreen[0];
            sy = yy + 300;
            aValue.start();
        }
        return false;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (isUseRipple && mView.isEnabled()) {
            aValue.setValueUpdateListener((animatorValue, v) -> {
                zj = v;
                if (v > 0.85) {
                    paint.setAlpha(0f);
                } else {
                    paint.setAlpha(0.2f);
                }
                mView.invalidate();
            });
            if (mView.getWidth() > mView.getHeight()) {
                canvas.drawCircle((float) sx, (float)sy, (float)(mView.getWidth() * zj), paint);
            } else {
                canvas.drawCircle((float)sx, (float)sy, (float)(mView.getHeight() * zj), paint);
            }
        }
    }

    @Override
    public void onRefreshed(Component component) {
    }
}
